Skip to main content

C++ Quick Reference

File Types: .h and .cpp Files

In C++, code is typically organized into two types of files:

What are Header Files (.h)

Header files contain declarations - they tell the compiler what functions, classes, and variables exist, but not how they work.

Think of a header file like a table of contents or menu at a restaurant - it lists what's available but doesn't contain the full recipe or instructions.

Why do we need header files?

  • They let other parts of your program know what functions and classes are available to use
  • They act like a "promise" - telling the compiler "these things exist, trust me"
  • They allow you to organize your code into separate files

What goes in .h files:

  • Include statements (#include) - Bringing in other header files that this file needs
  • Function declarations (what the function looks like) - Just the name, what it takes in, and what it gives back
  • Class definitions (what properties and methods a class has) - The blueprint of the class
  • Variable declarations - Telling the compiler a variable exists somewhere
  • Constants and definitions - Fixed values that won't change

Example - Drivetrain.h:

#pragma once

#include <frc/xrp/XRPMotor.h>
#include <frc2/command/SubsystemBase.h>

class Drivetrain : public frc2::SubsystemBase {
public:
Drivetrain();

// A function to drive the robot with tank-style controls.
// It takes a speed for the left side and a speed for the right side.
void TankDrive(double leftSpeed, double rightSpeed);

/**
* Will be called periodically whenever the CommandScheduler runs.
*/
void Periodic() override;

private:
// Components (e.g. motor controllers and sensors) should generally be
// declared private and exposed only through public methods.

// This creates an object for the left motor on channel 0
frc::XRPMotor m_left_motor{0};
// This creates an object for the right motor on channel 1
frc::XRPMotor m_right_motor{1};
};

What are Source Files (.cpp)

Source files contain definitions - they contain the actual code that does the work.

Think of a source file like the full recipe with step-by-step instructions, or like the actual kitchen where the cooking happens.

Why do we need source files?

  • They contain the "meat" of your program - the actual working code
  • They implement the promises made in the header files
  • They do the real work when your program runs

What goes in .cpp files:

  • Function implementations (the actual code that runs) - The detailed steps of what the function does
  • The detailed code for class methods - How each function in a class actually works
  • The main program logic - The code that gets executed when you run your program
  • Include statements - Bringing in the header files so you can use what's declared there

Example - Drivetrain.cpp:

#include "subsystems/Drivetrain.h"

Drivetrain::Drivetrain() = default;

// This is the definition of our TankDrive function.
// The code inside the curly braces {} is what runs when we call this function.
void Drivetrain::TankDrive(double leftSpeed, double rightSpeed) {
// This line tells our left motor object to set its speed to the value of leftSpeed.
m_left_motor.Set(leftSpeed);
// This line does the same for the right motor, using the rightSpeed value.
m_right_motor.Set(-rightSpeed);
}

// This method will be called once per scheduler run
void Drivetrain::Periodic() {}

Simple Rule of Thumb:

  • .h file: "What can this code do?" (the interface/promise)
    • Like a job description - it tells you what skills someone has
  • .cpp file: "How does this code actually work?" (the implementation/actual work)
    • Like watching someone actually do the job

Include Statements (#include)

In C++, #include statements are used to bring in code from other files or libraries. This allows you to use functions, classes, and variables that are defined elsewhere.

Why use #include?

  • To use code from the C++ Standard Library (like #include <iostream> for input/output)
  • To use your own code from other files (like #include "Drivetrain.h")
  • To use code from external libraries (like WPILib for FRC)

Syntax

#include <filename>   // For standard or external libraries
#include "filename" // For your own files in the project

Tip:

  • Use angle brackets < > for system or library headers.
  • Use double quotes " " for your own project files.

Member Variable Declarations

Member variables (also called fields or member objects) are variables that are declared inside a class. They represent the data or components that each object (instance) of the class will have.

Why use member variables?

  • To store information or state for each object
  • To represent hardware components (like motors or controllers) in robot code
  • To keep related data and functions together in a class

Example:

class RobotContainer {
public:
RobotContainer();
private:
Drivetrain m_drivetrain; // Subsystem member variable
frc::XboxController m_controller{0}; // Input device member variable
};

Tip:

  • The m_ prefix is a common convention to indicate a member variable.
  • Member variables can be objects (like Drivetrain or frc::XboxController) or basic types (like int).

Flow Charts

Flow charts are visual representations of the flow of a program. They use symbols to represent different types of actions or steps in a process.

Common Flowchart Shapes:

  • 🟩 Rectangle (Box): Represents an action or process step

    • Example: "Set motor speed" or "Calculate result"
    • This is where your program does something
  • 💎 Diamond: Represents a decision or question

    • Example: "Is age >= 18?" or "Is button pressed?"
    • This is where your program decides what to do next
    • Always has "Yes/No" or "True/False" arrows coming out
  • 🟢 Circle/Oval: Represents start or end points

    • "Start" - where your program begins
    • "End" - where your program finishes
  • ➡️ Arrows: Show the direction of flow

    • Tell you which step comes next
    • From diamonds, they're labeled with the decision result (Yes/No)

Example: Consider a program that checks if a person is old enough to vote (age 18 or older).


Variables and Data Types

Variables are used to store data in your program. In C++, you must declare a variable with a specific data type.

Common Data Types:

  • int: Stores integers (e.g., 42, -7).
  • double: Stores floating-point numbers (e.g., 3.14, -0.01).
  • char: Stores a single character (e.g., 'A', 'z').
  • bool: Stores true or false.
  • std::string: Stores text (requires #include <string>).

Example:

int age = 25;
double pi = 3.14159;
char grade = 'A';
bool isStudent = true;
std::string name = "John";

Control Structures

Control structures allow you to control the flow of your program.

If-Else Statements

Think of an if-else statement as a way for your program to make decisions. It's like asking a series of questions. The computer checks each question in order and runs the code for the first one that is true.

  • if: Asks the first question.
  • else if: If the first answer was "no," ask a second question.
  • else: If all the answers were "no," do this as a default.

This structure is perfect for choosing one action from several options.

Syntax:

if (condition1) {
// Code to execute if condition1 is true
} else if (condition2) {
// Code to execute if condition2 is true
} else {
// Code to execute if none of the conditions are true
}

Example:

int age = 20;
if (age < 13) {
std::cout << "You are a child.\n";
} else if (age < 18) {
std::cout << "You are a teenager.\n";
} else {
std::cout << "You are an adult.\n";
}

In this example:

  • If age is less than 13, the program prints "You are a child."
  • If age is between 13 and 17, the program prints "You are a teenager."
  • Otherwise, the program prints "You are an adult."

For Loop

The for loop is used to repeat a block of code a specific number of times. It consists of three parts:

  1. Initialization: Sets the starting value of a variable.
  2. Condition: Checks if the loop should continue.
  3. Increment/Decrement: Updates the variable after each iteration.

Syntax:

for (initialization; condition; increment/decrement) {
// Code to execute in each iteration
}

Example:

for (int i = 0; i < 5; i++) {
std::cout << i << "\n"; // Prints numbers from 0 to 4
}

While Loop

The while loop repeats a block of code as long as a condition is true. The condition is checked before each iteration.

Syntax:

while (condition) {
// Code to execute while condition is true
}

Example:

int i = 0;
while (i < 5) {
std::cout << i << "\n"; // Prints numbers from 0 to 4
i++; // Increments i by 1
}

Switch (Case) Statement

The switch statement is used to execute one block of code out of many options based on the value of a variable. It is often used as an alternative to multiple if-else statements.

Syntax:

switch (variable) {
case value1:
// Code to execute if variable == value1
break;
case value2:
// Code to execute if variable == value2
break;
// Add more cases as needed
default:
// Code to execute if none of the cases match
break;
}

Example:

int day = 3;

switch (day) {
case 1:
std::cout << "Monday\n";
break;
case 2:
std::cout << "Tuesday\n";
break;
case 3:
std::cout << "Wednesday\n";
break;
default:
std::cout << "Invalid day\n";
break;
}

In this example, the program checks the value of day. If day is 3, it prints "Wednesday". If no cases match, the default block runs.


Functions

Functions are reusable blocks of code that perform a specific task.

In C++, functions are usually declared in a header (.h) file and defined in a source (.cpp) file.

  • Declaration: Tells the compiler that a function exists and what its signature is (name, return type, parameters), but not what it does.

  • Definition: Provides the actual code (body) for the function.

Example:

Drivetrain.h (Declaration):

// Declaration (in header file)
void TankDrive(double leftSpeed, double rightSpeed);

Drivetrain.cpp (Definition):

// Definition (in source file)
void Drivetrain::TankDrive(double leftSpeed, double rightSpeed) {
m_left_motor.Set(leftSpeed);
m_right_motor.Set(-rightSpeed);
}

Input and Output

C++ uses std::cin for input and std::cout for output.

What are std::cin and std::cout?

  • std::cout: This is used to print output to the console. Think of it as a way to "talk" to the user by displaying messages or values.
  • std::cin: This is used to take input from the user. Think of it as a way to "listen" to what the user types.

Note: std::cin is not typically used in FRC programming because robot code does not interact with users via the console. Instead, inputs are usually taken from controllers or sensors.

Example:

#include <iostream>

int main() {
int age;
std::cout << "Enter your age: "; // Ask the user for their age
std::cin >> age; // Read the user's input and store it in the variable 'age'
std::cout << "You are " << age << " years old.\n"; // Print the user's age
return 0;
}

In this example:

  • std::cout displays the message "Enter your age: ".
  • std::cin waits for the user to type a number and stores it in the age variable.
  • std::cout then prints the message "You are [age] years old.".

Arrays and Vectors

Arrays

Fixed-size collections of elements of the same type.

int numbers[5] = {1, 2, 3, 4, 5};
std::cout << numbers[0]; // Access the first element

Vectors

Dynamic-size collections (requires #include <vector>).

#include <vector>

std::vector<int> numbers = {1, 2, 3};
numbers.push_back(4); // Add an element
std::cout << numbers[0]; // Access the first element

Classes and Objects

C++ is an object-oriented language. Classes are blueprints for creating objects.

Example:

class Car {
public:
std::string brand;
int speed;

void drive() {
std::cout << "Driving at " << speed << " mph.\n";
}
};

Car myCar;
myCar.brand = "Toyota";
myCar.speed = 60;
myCar.drive();

Pointers

Pointers store the address of a variable, not the variable itself. Think of it like a house address - it tells you where to find something.

Basic Syntax

int number = 42;
int* ptr = &number; // ptr stores the address of number

std::cout << ptr; // Prints the address (e.g., 0x7fff...)
std::cout << *ptr; // Prints 42 (goes to address and gets the value)

Key Operators

  • & = Get the address of a variable
  • * = Get the value at an address
  • -> = Call methods through a pointer

Common FRC Usage

// Pass subsystem to command
DriveCommand(Drivetrain* drivetrain) : m_drivetrain(drivetrain) {}

// Use the subsystem
void Execute() {
m_drivetrain->ArcadeDrive(0.5, 0.0); // Use -> for pointers
}

Quick Rules

  • Use &variable to get an address
  • Use *pointer to get the value at that address
  • Use pointer->method() to call methods
  • Don't use nullptr pointers (will crash!)

Comments

Comments are ignored by the compiler and are used to explain code.

  • Single-line comment: //
  • Multi-line comment: /* */

Example:

// This is a single-line comment
/*
This is a
multi-line comment
*/

Error Handling

Use try and catch blocks to handle exceptions.

Example:

try {
int x = 10 / 0; // Division by zero
} catch (std::exception& e) {
std::cout << "Error: " << e.what() << "\n";
}

Namespaces

Namespaces in C++ are used to organize code and prevent naming conflicts. They group related classes, functions, and variables under a unique name.

  • Avoid Naming Conflicts: If two libraries define a function or variable with the same name, namespaces ensure they don't clash.
  • Organize Code: Group related functionality together for better readability.

Part 1: Defining Values

In this part, we define constants inside a namespace.

// RobotConfig.h
#pragma once

```cpp
namespace DrivetrainConstants {

constexpr static double kMoveSpeed = 0.75; // Speed for moving forward and backward (1 = max speed, 0 = stopped)
constexpr static double kTurnSpeed = 0.5; // Speed for turning left and right (1 = max speed, 0 = stopped)
}
  • namespace DrivetrainConstants: This creates a container or a "scope" named DrivetrainConstants. It's used to group related variables together to keep the code organized and to avoid naming conflicts.
  • constexpr: This keyword declares the variable as a "constant expression." It means its value is fixed and must be known when the code is compiled.
  • static: This keyword limits the variable's visibility to just this file. It helps prevent conflicts if another file were to accidentally declare a variable with the same name.
  • double: This is the data type, which means the variable can hold a number with a decimal point. This is suitable for representing speeds that aren't whole numbers.
  • kMoveSpeed: This is the name of the variable. The k prefix is a common programming convention (especially in FRC) to indicate that the variable is a constant.

Part 2: Reading and Using Values

In this part, we access the values from the namespace and use them in calculations.

// main.cpp
#include "RobotConfig.h" // Include the namespace file

int main() {
// Access the variables using the namespace
double current_speed = DrivetrainConstants::kMoveSpeed;
double current_turning_speed = DrivetrainConstants::kTurnSpeed;

return 0;
}